import CodeBlock from "../../../component/CodeBlock";
import { code } from "./codeData";
import { useEffect, useState, useRef } from "react";

interface Channel {
    id: number;
    name: string;
}
function HooksTest() {
    const url = 'http://geek.itheima.net/v1_0/channels'
    const [list, setList] = useState<Channel[]>([])
    const [count, setCount] = useState(0)
    const [enabled, setEnabled] = useState(true)
    const timerRef = useRef<number | null>(null)

    // 示例1: 基本的数据获取 - 仅在组件挂载时执行一次
    const getData = async () => {
        try {
            const res = await fetch(url)
            const jsonRes = await res.json()
            setList(jsonRes.data.channels)
        } catch (error) {
            console.error("获取数据失败:", error)
        }
    }

    useEffect(() => {
        getData()
    }, [])

    // 示例2: 带有清理函数的useEffect - 定时器
    useEffect(() => {
        if (enabled) {
            timerRef.current = setInterval(() => {
                setCount(c => c + 1)
            }, 1000)
        }

        // 清理函数 - 在组件卸载或依赖项变化前执行
        return () => {
            if (timerRef.current) {
                clearInterval(timerRef.current)
            }
        }
    }, [enabled]) // 依赖项数组，当enabled变化时重新执行

    // 示例3: 条件执行副作用
    useEffect(() => {
        if (enabled) {
            console.log("计数器已启用")
        } else {
            console.log("计数器已禁用")
        }
    }, [enabled])

    // 示例4: 使用isMounted模式防止内存泄漏
    useEffect(() => {
        let isMounted = true

        const fetchDataWithAbort = async () => {
            try {
                const res = await fetch(url)
                const jsonRes = await res.json()
                if (isMounted) {
                    setList(jsonRes.data.channels)
                }
            } catch (error) {
                if (isMounted) {
                    console.error("获取数据失败:", error)
                }
            }
        }

        fetchDataWithAbort()

        // 清理函数 - 将isMounted设为false
        return () => {
            isMounted = false
        }
    }, [])

    return (<div className="tab-pane">
        <h1>Hooks</h1>
        <p>Hooks是React 16.8引入的新特性，它们允许你在不编写类组件的情况下使用state和其他React特性。</p>

        <h3>内置Hooks</h3>
        <p>React提供了一些内置的Hooks：</p>
        <ul>
            <li><strong>useState</strong>：在函数组件中添加state</li>
            <li><strong>useEffect</strong>：在函数组件中执行副作用操作</li>
            <li><strong>useContext</strong>：在函数组件中订阅React Context</li>
            <li><strong>useReducer</strong>：在函数组件中使用Reducer</li>
            <li><strong>useCallback</strong>：返回一个记忆化的回调函数</li>
            <li><strong>useMemo</strong>：返回一个记忆化的值</li>
            <li><strong>useRef</strong>：返回一个可变的ref对象</li>
            <li><strong>useImperativeHandle</strong>：自定义暴露给父组件的ref值</li>
            <li><strong>useLayoutEffect</strong>：在DOM更新后同步执行副作用</li>
            <li><strong>useDebugValue</strong>：在React DevTools中显示自定义标签</li>
        </ul>

        <h3>自定义Hook</h3>
        <p>你可以创建自己的Hook来在组件之间重用状态逻辑。</p>
        <CodeBlock code={code.hooks1}></CodeBlock>

        <h3>useEffect用法</h3>
        <p>useEffect是React中处理副作用的Hook，它允许你在函数组件中执行操作如数据获取、订阅或手动修改DOM。</p>

        <h4>1. 基本用法 - 组件挂载时执行</h4>
        <p>下面的useEffect只在组件首次渲染后执行一次，类似于类组件中的componentDidMount：</p>
        <CodeBlock code={`useEffect(() => {
    getData()
}, [])`}></CodeBlock>

        <h4>2. 依赖项控制执行时机</h4>
        <p>当依赖项数组中的值发生变化时，useEffect会重新执行：</p>
        <CodeBlock code={`useEffect(() => {
    // 当enabled状态变化时执行
    if (enabled) {
        console.log("功能已启用")
    }
}, [enabled])`}></CodeBlock>

        <h4>3. 清理副作用</h4>
        <p>useEffect可以返回一个清理函数，React会在组件卸载或重新执行effect前调用它：</p>
        <CodeBlock code={`useEffect(() => {
    // 设置定时器
    const timer = setInterval(() => {
        // 定时器逻辑
    }, 1000)

    // 清理函数 - 清除定时器防止内存泄漏
    return () => {
        clearInterval(timer)
    }
}, [])`}></CodeBlock>

        <h4>4. 防止组件卸载后设置状态</h4>
        <p>使用isMounted模式防止在组件卸载后设置状态导致的错误：</p>
        <CodeBlock code={`useEffect(() => {
    let isMounted = true

    const fetchData = async () => {
        const res = await fetch(url)
        const data = await res.json()
        if (isMounted) {
            // 只有在组件仍然挂载时才设置状态
            setData(data)
        }
    }

    fetchData()

    // 清理函数
    return () => {
        isMounted = false
    }
}, [])`}></CodeBlock>

        <h4>5. 实际应用示例</h4>
        <p>当前组件中的useEffect应用示例：</p>
        <ul>
            <li>定时器计数器：{count}秒</li>
            <li>状态: {enabled ? "已启用" : "已禁用"}</li>
            <li>
                <button className="mainButton" onClick={() => setEnabled(!enabled)}>
                    {enabled ? "禁用" : "启用"} 计时器
                </button>
            </li>
        </ul>

        <h4>6. 副作用列表</h4>
        <p>常见的副作用操作及其清理方法：</p>
        <ul>
            <li><strong>数据获取</strong>：通常不需要清理，除非使用AbortController</li>
            <li><strong>订阅</strong>：返回取消订阅的函数</li>
            <li><strong>定时器</strong>：返回清除定时器的函数</li>
            <li><strong>手动DOM修改</strong>：通常不需要清理，除非添加了事件监听器</li>
            <li><strong>事件监听器</strong>：返回移除监听器的函数</li>
        </ul>

        <h4>当前获取的数据列表：</h4>
        <ul style={{ display: 'grid', gridTemplateColumns: 'repeat(5,1fr)', gridGap: '10px' }}>
            {
                list.map(item => {
                    return <li key={item.id}>{item.name}</li>
                })
            }
        </ul>

    </div>);
}

export default HooksTest;